/**
 * Plugin developed to save html forms data to LocalStorage to restore them after browser crashes, tabs closings
 * and other disasters.
 *
 * https://github.com/simsalabim/sisyphus
 *
 * @author Alexander Kaupanin <kaupanin@gmail.com>
 * @license MIT - see https://github.com/simsalabim/sisyphus/blob/master/MIT-LICENSE
 */
var keyArray=[];/*存所有key值*/

( function( $ ) {
    /*    var config= {
            childList: true,   /!*子节点的变动*!/
            subtree: true,    /!*后代节点变动*!/
            attributes:true, /!*属性变动*!/
            characterData:true, /!*节点内容或文本变化*!/
            attributeOldValue:true,/!*属性变动老数据*!/
            characterDataOldValue:true,/!*节点内容或文本变化老数据*!/
        };
        ready('form textarea,form input,form select', function(element){
            var checkNode = new MutationObserver(function (mutations) {
                mutations.forEach(function (record) {
                        })
                    })
            if($(element).attr('id')=='narrator'){
                debugger
                var a;
            }
                    checkNode.observe(element , config)
        });*/
    function getElementIdentifier(el) {
        if(el.attr('sisSaveType')||el.is('form')){
            return '[inpatientId=' + getRequestUrl().inpatientId + '][sisSaveType=' + el.attr( "sisSaveType" ) + '][id=' + el.attr( "id" ) + '][name=' + el.attr( "name" ) + ']';
        }else{
            return '[id=' + el.attr( "id" ) + '][name=' + el.attr( "name" ) + ']';
        }
    }
    $.fn.sisyphus = function( options ) {
        var identifier = $.map( this, function( obj ) {
            return getElementIdentifier( $( obj ) );
        }).join();

        var sisyphus = Sisyphus.getInstance( identifier );
        sisyphus.protect( this, options );
        return sisyphus;
    };

    var browserStorage = {};

    /**
     * Check if local storage or other browser storage is available
     *
     * @return Boolean
     */
    browserStorage.isAvailable = function() {
        if ( typeof $.jStorage === "object" ) {
            return true;
        }
        try {
            return localStorage.getItem;
        } catch ( e ) {
            return false;
        }
    };

    /**
     * Set data to browser storage
     *
     * @param [String] key
     * @param [String] value
     *
     * @return Boolean
     */
    browserStorage.set = function( key, value ) {
        if ( typeof $.jStorage === "object" ) {
            $.jStorage.set( key, value + "" );
        } else {
            try {
                localStorage.setItem( key, value + "" );
            } catch ( e ) {
                //QUOTA_EXCEEDED_ERR
            }
        }
    };

    /**
     * Get data from browser storage by specified key
     *
     * @param [String] key
     *
     * @return string
     */
    browserStorage.get = function( key ) {
        if ( typeof $.jStorage === "object" ) {
            var result = $.jStorage.get( key );
            return result ? result.toString() : result;
        } else {
            return localStorage.getItem( key);

        }
    };

    /**
     * Delete data from browser storage by specified key
     *
     * @param [String] key
     *
     * @return void
     */
    browserStorage.remove = function( key ) {
        if ( typeof $.jStorage === "object" ) {
            $.jStorage.deleteKey( key );
        } else {
            localStorage.removeItem( key );
        }
    };

    Sisyphus = ( function() {
        var params = {
            instantiated: [],
            started: []
        };
        var CKEDITOR = window.CKEDITOR;

        function init () {

            return {
                setInstanceIdentifier: function( identifier ) {
                    this.identifier = identifier;
                },

                getInstanceIdentifier: function() {
                    return this.identifier;
                },

                /**
                 * Set plugin initial options
                 *
                 * @param [Object] options
                 *
                 * @return void
                 */
                setInitialOptions: function ( options ) {
                    var defaults = {
                        excludeFields: [],
                        customKeySuffix: "",
                        locationBased: false,
                        timeout: 0,
                        autoRelease: true,
                        onBeforeSave: function() {},
                        onSave: function() {},
                        onBeforeRestore: function() {},
                        onRestore: function() {},
                        onRelease: function() {}
                    };
                    this.options = this.options || $.extend( defaults, options );
                    this.browserStorage = browserStorage;
                },

                /**
                 * Set plugin options
                 *
                 * @param [Object] options
                 *
                 * @return void
                 */
                setOptions: function ( options ) {
                    this.options = this.options || this.setInitialOptions( options );
                    this.options = $.extend( this.options, options );
                },

                /**
                 * Protect specified forms, store it's fields data to local storage and restore them on page load
                 *
                 * @param [Object] targets		forms object(s), result of jQuery selector
                 * @param Object options			plugin options
                 *
                 * @return void
                 */
                protect: function( targets, options ) {
                    this.setOptions( options );
                    targets = targets || {};
                    var self = this;
                    this.targets = this.targets || [];
                    if ( self.options.name ) {
                        this.href = self.options.name;
                    } else {
                        this.href = location.hostname + location.pathname + location.search + location.hash;
                    }
                    this.targets = $.merge( this.targets, targets );
                    this.targets = $.unique( this.targets );
                    this.targets = $( this.targets );
                    if ( ! this.browserStorage.isAvailable() ) {
                        return false;
                    }

                    var callback_result = self.options.onBeforeRestore.call( self );
                    if ( callback_result === undefined || callback_result ) {
                        self.restoreAllData();
                    }

                    if ( this.options.autoRelease ) {
                        self.bindReleaseData();
                    }

                    if ( ! params.started[ this.getInstanceIdentifier() ] ) {
                        if ( self.isCKEditorPresent() ) {
                            var intervalId = setInterval( function() {
                                if (CKEDITOR.isLoaded) {
                                    clearInterval(intervalId);
                                    self.bindSaveData();
                                    params.started[ self.getInstanceIdentifier() ] = true;
                                }
                            }, 100);
                        } else {
                            self.bindSaveData();
                            params.started[ self.getInstanceIdentifier() ] = true;
                        }
                    }
                },

                isCKEditorPresent: function() { /*富文本编辑器*/
                    if ( this.isCKEditorExists() ) {
                        CKEDITOR.isLoaded = false;
                        CKEDITOR.on('instanceReady', function() {
                            CKEDITOR.isLoaded = true;
                        } );
                        return true;
                    } else {
                        return false;
                    }
                },

                isCKEditorExists: function() {
                    return typeof CKEDITOR !== "undefined";
                },

                findFieldsToProtect: function( target ) {
                    return target.find( ":input,.specialObject,img" ).not( ":submit" ).not( ":reset" ).not( ":button" ).not( ":file" ).not( ":password" ).not( ":disabled" ).not( "[readonly]" ).not( "[name=superiorUserId],[name=recordUserId]" );
                },
                getValue:false,
                /**
                 * Bind saving data
                 *
                 * @return void
                 */
                bindSaveData: function(config) {
                    var self = this;
                    if(config && config.getValue){/*判断是否是取值*/
                        self.getValue=true
                    }
                    if ( self.options.timeout ) {
                        self.saveDataByTimeout();
                    }
                    if(!self.targets){
                        self.targets=$('.active-iframe',top.document).contents().find('form')
                        if($('.active-iframe',top.document).contents().find('#addHtml').length){
                            self.targets=$('.active-iframe',top.document).contents().find('#addHtml').contents().find('form')
                        }
                    }
                    /*self.targets.each( function() {
                        var targetFormIdAndName = getElementIdentifier( $( this ) );
                        self.findFieldsToProtect( $( this ) ).each( function() {
                            if ( $.inArray( this, self.options.excludeFields ) !== -1 ) {
                                // Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
                                return true;
                            }
                            var field = $( this );
                            var prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( field ) + self.options.customKeySuffix;
                            if ( field.is( ":text" ) || field.is( "textarea" ) ||field.hasClass( "specialObject" ) ) {
                                if ( ! self.options.timeout ) {
                                    self.bindSaveDataImmediately( field, prefix );
                                }
                            }
                            //self.bindSaveDataOnChange( field );
                        } );
                    } );*/
                    self.bindSaveDataInput()
                    //self.bindSaveChange()
                    self.getValue=false;
                },
                /* 处理元素属性 取得所有属性名及值 返回一个新对象 */
                disposeAttribute: function (field) {
                    var newAttributeObj={}
                    var attribute=field[0].attributes||field.attributes;
                    for(var i=0;i<attribute.length;i++){
                        var inner=attribute[i];
                        newAttributeObj[inner.name]=inner.value;
                    }
                    return JSON.stringify(newAttributeObj)
                },

                /**
                 * Save all protected forms data to Local Storage.
                 * Common method, necessary to not lead astray user firing 'data is saved' when select/checkbox/radio
                 * is changed and saved, while text field data is saved only by timeout
                 *
                 * @return void
                 */
                saveAllData: function() {
                    var self = this;
                    self.targets.each( function() {
                        var targetFormIdAndName = getElementIdentifier( $( this ) );
                        var multiCheckboxCache = {};

                        self.findFieldsToProtect( $( this) ).each( function(i,ele) {
                            var field = $( this );
                            if ( $.inArray( this, self.options.excludeFields ) !== -1 || ( field.attr( "name" ) === undefined && field.attr( "id" ) === undefined ) ) {
                                // Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
                                return true;
                            }
                            var prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( field ) + self.options.customKeySuffix;
                            var value = field.val();
                            if(field.is(':text')){
                                value +='[;]'+self.disposeAttribute(field)
                            }else if(field.hasClass('specialObject')){
                                var text=field.html();
                                value=text
                            }
                            if ( field.is(":checkbox") ) {
                                var name = field.attr( "name" );
                                if ( name !== undefined && name.indexOf( "[" ) !== -1 ) {
                                    if ( multiCheckboxCache[ name ] === true ) {
                                        return;
                                    }
                                    value = [];
                                    $( "[name='" + name +"']:checked" ).each( function() {
                                        value.push( $( this ).val() );
                                    } );
                                    multiCheckboxCache[ name ] = true;
                                } else {
                                    value = field.is( ":checked" );
                                }
                                self.saveToBrowserStorage( prefix, value, false );
                            } else if ( field.is( ":radio" ) ) {
                                if ( field.is( ":checked" ) ) {
                                    value = field.val();
                                    self.saveToBrowserStorage( prefix, value, false );
                                }
                            } else {
                                if ( self.isCKEditorExists() ) {
                                    var editor = CKEDITOR.instances[ field.attr("name") ] || CKEDITOR.instances[ field.attr("id") ];
                                    if ( editor ) {
                                        editor.updateElement();
                                        self.saveToBrowserStorage( prefix, field.val(), false);
                                    } else {
                                        self.saveToBrowserStorage( prefix, value, false );
                                    }
                                } else {
                                    self.saveToBrowserStorage( prefix, value, false );
                                }
                            }
                            if(i+1==self.findFieldsToProtect( $( this) ).length){

                            }
                        } );
                    } );
                    self.options.onSave.call( self );
                },

                /**
                 * Restore forms data from Local Storage
                 *
                 * @return void
                 */
                restoreAllData: function(config) {
                    var self = this;
                    if(config && config.getValue){/*判断是否是取值*/
                        self.getValue=true
                    }
                    var restored = false;
                    var num=0;
                    if(!self.targets){
                        self.targets=$('.active-iframe',top.document).contents().find('form')
                        if($('.active-iframe',top.document).contents().find('#addHtml').length){
                            self.targets=$('.active-iframe',top.document).contents().find('#addHtml').contents().find('form')
                        }
                    }
                    self.targets.each( function() {
                        var target = $( this );
                        var targetFormIdAndName = getElementIdentifier( $( this ) );
                        window.zqimg=true;/*知情示意图选择控制*/
                        self.findFieldsToProtect( target ).each( function() {
                            if ( $.inArray( this, self.options.excludeFields ) !== -1 ) {
                                // Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
                                return true;
                            }
                            var field = $( this );
                            var prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( field ) + self.options.customKeySuffix;
                            var resque = self.browserStorage.get( prefix );
                            if ( resque !== null ) {
                                self.restoreFieldsData( field, resque );
                                restored = true;
                                num++
                            }
                        } );
                        window.zqimg=false;
                    } );

                    if ( restored ) {
                        self.options.onRestore.call( self );
                    }
                    if( num > 0 ) {
                        top.drafContain=true;
                    }else{
                        top.drafContain=false;
                    }
                    self.getValue=false;
                },

                /**
                 * Restore form field data from local storage
                 *
                 * @param Object field		jQuery form element object
                 * @param String resque	 previously stored fields data
                 *
                 * @return void
                 */
                restoreFieldsData: function( field, resque ) {
                    if ( field.attr( "name" ) === undefined && field.attr( "id" ) === undefined ) {
                        return false;
                    }
                    var name = field.attr( "name" );
                    if ( field.is( ":checkbox" ) && resque !== "false" && ( name === undefined || name.indexOf( "[" ) === -1 ) ) {
                        // If we aren't named by name (e.g. id) or we aren't in a multiple element field
                        field.trigger('click');
                        field.prop( "checked", true );
                    } else if( field.is( ":checkbox" ) && resque === "false" && ( name === undefined || name.indexOf( "[" ) === -1 ) ) {
                        // If we aren't named by name (e.g. id) or we aren't in a multiple element field
                        field.prop( "checked", false );
                    } else if ( field.is( ":radio" ) ) {
                        if ( 'true' === resque ) {
                            field.trigger('click');
                            field.prop( "checked", true );
                        }
                    } else if ( name === undefined || name.indexOf( "[" ) === -1 ) {
                        // If we aren't named by name (e.g. id) or we aren't in a multiple element field
                        if(field.is(':text')||field.is('img')){
                            var index=resque.indexOf('[;]');
                            if(index!=-1){
                                var objAttribute=JSON.parse(resque.slice(index+3));
                                for(var name in objAttribute){
                                    field.attr(name,objAttribute[name])
                                }
                                field.val( resque.slice(0,index) );
                                return true
                            }
                        } else if( field.hasClass( "specialObject" )) {
                            field.html(resque)
                        }

                        field.val( resque );
                        if(field.is('select')){
                            field.change()
                        }
                    }  else {
                        resque = resque.split( "," );
                        field.val( resque );
                    }
                },

                /**
                 * Bind immediate saving (on typing/checking/changing) field data to local storage when user fills it
                 *
                 * @param Object field		jQuery form element object
                 * @param String prefix	 prefix used as key to store data in local storage
                 *
                 * @return void
                 */
                bindSaveDataImmediately: function( field, prefix ) {
                    var self = this;
                    if ( 'onpropertychange' in field ) {
                        field.get(0).onpropertychange = function() {
                            self.saveToBrowserStorage( prefix, field.val() );
                        };
                    } else {
                        field.get(0).oninput = function() {
                            var value=field.val();
                            if(field.hasClass( "specialObject" )){
                                value=field.html();
                            }
                            if(field.is(':text')){
                                value +='[;]'+self.disposeAttribute(field)
                            }
                            self.saveToBrowserStorage( prefix, value );
                        };
                    }
                    field.get(0).onchange = function() {
                        var value=field.val();
                        if(field.hasClass( "specialObject" )){
                            value=field.html();
                        }
                        if(field.is(':text')){
                            value +='[;]'+self.disposeAttribute(field)
                        }
                        self.saveToBrowserStorage( prefix, value );
                    };
                    field.on('DOMNodeInserted',function () { /* dom节点变化监听存值 */
                        if(field.attr('name')=='mensesHistory'||top.getValue) return
                        var time=setTimeout(function () {
                            var value=field.html()
                            self.saveToBrowserStorage( prefix, value );
                            clearTimeout(time)
                        },50)
                    })
                    if ( this.isCKEditorExists() ) {
                        var editor = CKEDITOR.instances[ field.attr("name") ] || CKEDITOR.instances[ field.attr("id") ];
                        if ( editor ) {
                            editor.document.on( 'keyup', function() {
                                editor.updateElement();
                                self.saveToBrowserStorage( prefix, field.val() );
                            } );
                        }
                    }
                },
                bindSaveDataInput : function () {
                    var self = this;
                    var target='form textarea,form input,form select,form .specialObject,img'; /*监听元素*/
                    $('body').on('keyup change blur',target,function (e) {
                        if(e.isPropagationStopped()) return /*阻止jq绑定事件执行2次*/
                        var targetFormIdAndName = getElementIdentifier( $( this ).parents('form') );
                        var field=$(this);
                        /*id 和 name为空跳出*/
                        if ( $.inArray( this, self.options.excludeFields ) !== -1 || ( field.attr( "name" ) === undefined && field.attr( "id" ) === undefined ) ) {
                            return
                        }
                        var prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( field ) + self.options.customKeySuffix;
                        var value=field.val();
                        if(field.hasClass( "specialObject" )){
                            value=field.html();
                            self.saveToBrowserStorage( prefix, value );
                        }else if(field.parents(".specialObject").length){
                            field=field.parents(".specialObject");
                            prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( field ) + self.options.customKeySuffix;
                            value=field.html();
                            self.saveToBrowserStorage( prefix, value );
                        }
                        else if(field.is(':text')||field.is('img')){
                            value +='[;]'+self.disposeAttribute(field);
                            self.saveToBrowserStorage( prefix, value );
                        }else if ( field.is(":checkbox") ) {
                            var name = field.attr( "name" );
                            if ( name !== undefined && name.indexOf( "[" ) !== -1 ) {
                                if ( multiCheckboxCache[ name ] === true ) {
                                    return;
                                }
                                value = [];
                                $( "[name='" + name +"']:checked" ).each( function() {
                                    value.push( $( this ).val() );
                                } );
                                multiCheckboxCache[ name ] = true;
                            } else {
                                value = field.is( ":checked" );
                            }
                            self.saveToBrowserStorage( prefix, value, false );
                        }
                        else if ( field.is( ":radio" ) ) {
                            if ( field.is( ":checked" ) ) {
                                value = field.val();
                                self.saveToBrowserStorage( prefix, true, false );
                                field.siblings().each(function () {
                                    if($(this).is( ":radio" )){
                                        var prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( $(this) ) + self.options.customKeySuffix;
                                        self.saveToBrowserStorage( prefix, false, false );
                                    }
                                })
                            }
                        }else {
                            if ( self.isCKEditorExists() ) { /*富文本编辑器判断*/
                                var editor = CKEDITOR.instances[ field.attr("name") ] || CKEDITOR.instances[ field.attr("id") ];
                                if ( editor ) {
                                    editor.updateElement();
                                    self.saveToBrowserStorage( prefix, field.val(), false);
                                } else {
                                    self.saveToBrowserStorage( prefix, value, false );
                                }
                            } else {
                                self.saveToBrowserStorage( prefix, value, false );
                            }
                        }
                        e.stopPropagation()
                    });
                    $('body').on('DOMNodeInserted','.specialObject',function (e) {  /*元素节点变化监听*/
                        var targetFormIdAndName = getElementIdentifier( $( this ).parents('form') );
                        var field=$(this)
                        var prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( field ) + self.options.customKeySuffix;
                        if(field.attr('name')=='mensesHistory') return
                        var time=setTimeout(function () {
                            var value=field.html()
                            self.saveToBrowserStorage( prefix, value );
                            clearTimeout(time)
                        },50)
                    })
                },

                /**
                 * Save data to Local Storage and fire callback if defined
                 *
                 * @param String key
                 * @param String value
                 * @param Boolean [true] fireCallback
                 *
                 * @return void
                 */
                saveToBrowserStorage: function( key, value, fireCallback ) {
                    var self = this;

                    var callback_result = self.options.onBeforeSave.call( self );
                    if ( callback_result !== undefined && callback_result === false ) {
                        return;
                    }

                    // if fireCallback is undefined it should be true
                    fireCallback = fireCallback === undefined ? true : fireCallback;
                    this.browserStorage.set( key, value );
                    if ( fireCallback && value !== "" ) {
                        this.options.onSave.call( this );
                    }
                },

                /**
                 * Bind saving field data on change
                 *
                 * @param Object field		jQuery form element object
                 *
                 * @return void
                 */
                bindSaveDataOnChange: function( field ) {
                    var self = this;
                    if(!$(field).is('select')&&!$(field).is(':radio')&&!$(field).is(':checkbox')) return
                    field.change( function() {
                        if(!self.getValue){ /*取值时取消事件*/
                            self.saveAllData();
                        }
                    } );
                },
                bindSaveChange :function () {
                    var self = this;
                    var multiCheckboxCache = {};
                    $('body').on('change','select,input',function (e) {
                        var that=this;
                        if(!self.getValue){ /*取值时取消事件*/
                            self.targets.each( function() {
                                var targetFormIdAndName = getElementIdentifier( $( this ) );
                                var multiCheckboxCache = {};
                                var field = $( that );
                                if ( $.inArray( this, self.options.excludeFields ) !== -1 || ( field.attr( "name" ) === undefined && field.attr( "id" ) === undefined ) ) {
                                    // Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
                                    return true;
                                }
                                var prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( field ) + self.options.customKeySuffix;
                                var value = field.val();
                                if(field.is(':text')){
                                    value +='[;]'+self.disposeAttribute(field)
                                }else if(field.hasClass('specialObject')){
                                    var text=field.html();
                                    value=text
                                }
                                if ( field.is(":checkbox") ) {
                                    var name = field.attr( "name" );
                                    if ( name !== undefined && name.indexOf( "[" ) !== -1 ) {
                                        if ( multiCheckboxCache[ name ] === true ) {
                                            return;
                                        }
                                        value = [];
                                        $( "[name='" + name +"']:checked" ).each( function() {
                                            value.push( $( this ).val() );
                                        } );
                                        multiCheckboxCache[ name ] = true;
                                    } else {
                                        value = field.is( ":checked" );
                                    }
                                    self.saveToBrowserStorage( prefix, value, false );
                                } else if ( field.is( ":radio" ) ) {
                                    if ( field.is( ":checked" ) ) {
                                        value = field.val();
                                        self.saveToBrowserStorage( prefix, true, false );
                                        field.siblings().each(function () {
                                            if($(this).is( ":radio" )){
                                                var prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( $(this) ) + self.options.customKeySuffix;
                                                self.saveToBrowserStorage( prefix, false, false );
                                            }
                                        })
                                    }
                                } else {
                                    if ( self.isCKEditorExists() ) {
                                        var editor = CKEDITOR.instances[ field.attr("name") ] || CKEDITOR.instances[ field.attr("id") ];
                                        if ( editor ) {
                                            editor.updateElement();
                                            self.saveToBrowserStorage( prefix, field.val(), false);
                                        } else {
                                            self.saveToBrowserStorage( prefix, value, false );
                                        }
                                    } else {
                                        self.saveToBrowserStorage( prefix, value, false );
                                    }
                                }
                            } );
                            self.options.onSave.call( self );
                        }
                    })
                },
                /**
                 * Saving (by timeout) field data to local storage when user fills it
                 *
                 * @return void
                 */
                saveDataByTimeout: function() {
                    var self = this;
                    var targetForms = self.targets;
                    setTimeout( ( function() {
                        function timeout() {
                            self.saveAllData();
                            setTimeout( timeout, self.options.timeout * 1000 );
                        }
                        return timeout;
                    } )( targetForms ), self.options.timeout * 1000 );
                },

                /**
                 * Bind release form fields data from local storage on submit/reset form
                 *
                 * @return void
                 */
                bindReleaseData: function() {
                    var self = this;
                    self.targets.each( function() {
                        var target = $( this );
                        var formIdAndName = getElementIdentifier( target );
                        $( this ).bind( "submit reset", function() {
                            self.releaseData( formIdAndName, self.findFieldsToProtect( target ) );
                        } );
                    } );
                },

                /**
                 * Manually release form fields
                 *
                 * @return void
                 */
                manuallyReleaseData: function(target) {
                    var self = this;
                    var formIdAndName = getElementIdentifier( target );
                    self.releaseData( formIdAndName, self.findFieldsToProtect( target ) )
                    /*self.targets.each( function() {
                        var target = $( this );
                        var formIdAndName = getElementIdentifier( target );
                        self.releaseData( formIdAndName, self.findFieldsToProtect( target ) );
                    } );*/
                },

                /**
                 * Bind release form fields data from local storage on submit/resett form
                 *
                 * @param String targetFormIdAndName	a form identifier consists of its id and name glued
                 * @param Object fieldsToProtect		jQuery object contains form fields to protect
                 *
                 * @return void
                 */
                releaseData: function( targetFormIdAndName, fieldsToProtect ) {
                    var released = false;
                    var self = this;

                    // Released form, are not started anymore. Fix for ajax loaded forms.
                    params.started[ self.getInstanceIdentifier() ] = false;

                    fieldsToProtect.each( function() {
                        if ( $.inArray( this, self.options.excludeFields ) !== -1 ) {
                            // Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
                            return true;
                        }
                        var field = $( this );
                        var prefix = (self.options.locationBased ? self.href : "") + targetFormIdAndName + getElementIdentifier( field ) + self.options.customKeySuffix;
                        self.browserStorage.remove( prefix );
                        released = true;
                    } );
                    if ( released ) {
                        self.options.onRelease.call( self );
                    }
                }

            };
        }

        return {
            getInstance: function( identifier ) {
                if ( ! params.instantiated[ identifier ] ) {
                    params.instantiated[ identifier ] = init();
                    params.instantiated[ identifier ].setInstanceIdentifier( identifier );
                    params.instantiated[ identifier ].setInitialOptions();
                }
                if ( identifier ) {
                    return params.instantiated[ identifier ];
                }
                return params.instantiated[ identifier ];
            },

            free: function() {
                params = {
                    instantiated: [],
                    started: []
                };
                return null;
            },
            version: '1.1.3'
        };
    } )();
    top.Sisyphus=Sisyphus.getInstance();
} )( jQuery );
